/*
*  Copyright (C) 2009  Peter Kist & Jan Ripke
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __core_vfs_h
#define __core_vfs_h 1

#if _WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#include <string>
#include <sstream>

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

namespace galaxy {
    namespace core {
        namespace functors {

            /** widen a string (ansi to unicode) */
            class WidenString {
            public:
                std::wstring operator()(const std::string& str) {
                    std::wostringstream wstm;
                    const std::ctype<wchar_t>& ctfacet = 
                        std::use_facet< std::ctype<wchar_t> >( wstm.getloc() ) ;
                    for( size_t i=0 ; i<str.size() ; ++i ) 
                        wstm << ctfacet.widen( str[i] ) ;
                    return wstm.str() ;
                }
            };
 
            /** narrow a string (unicode to ansi) */
            class NarrowString {
            public:
                std::string operator()(const std::wstring& str) {
                    std::ostringstream stm ;
                    const std::ctype<char>& ctfacet = 
                        std::use_facet< std::ctype<char> >( stm.getloc() ) ;
                    for( size_t i=0 ; i<str.size() ; ++i ) 
                        stm << ctfacet.narrow( str[i], 0 ) ;
                    return stm.str() ;
                }
            };


            class Base {
            public:
                std::string operator()(std::string& filename) {
                    std::string::size_type offset = filename.find_first_of(".");
                    if (offset != std::string::npos) {
                        return filename.erase (offset);
                    }
                    return filename;
                }
            };


            class Extension {
            public:
                /** extracts the extension from filename */
                std::string operator ()(fs::path path) {
                    std::string filename (path.filename ());

                    if (filename.empty()) {
                        std::string::size_type offset = filename.find_last_of (".");
                        if (offset != std::string::npos) {
                            return filename.substr (offset + 1); // skip '.'
                        }
                    }

                    return "";
                }

                /** add extension if path has no extension yet */
                std::string operator () (fs::path path, std::string extension) {
                    std::string current_ext (this->operator()(path));
                    if (! current_ext.empty()) {
                        if (current_ext == extension) {
                            return path.string();
                        } else {
                            Base base;
                            return base(std::string(path.string ())) + "." + extension;
                        }
                    } else {
                        return path.string() + "." + extension;
                    }
                }
            };

            /** Functor that will fetch the name of the executable that was started */
            class ApplicationName {
            public:
                fs::path operator()() {
#if _WIN32
                    TCHAR pathbuf[MAX_PATH];

                    if(! GetModuleFileName(0, pathbuf, MAX_PATH)) {
                        return "";
                    }

                    NarrowString narrow;
                    std::string result = narrow (std::wstring(pathbuf));
                    return result.c_str();
#else
                    return ""; // not supported on non-windows platforms yet
#endif
                }
            };


        } // namespace functors
    } // namespace core
} // namespace galaxy

#endif // __core_vfs_h